package cn.saltice.idempotence.idem.store;

import cn.saltice.idempotence.idem.enums.IdempotentStorageTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @program: idempotence
 * @description: MySQL存储 ， 比较简单
 * @author: Mr.Liu
 * @create: 2020-10-04 23:12
 **/
@Slf4j
@Component("IdempotentMysqlStorage")
public class IdempotentMysqlStorage implements IdempotentStorage{
    @Resource
    private JdbcTemplate jdbcTemplate;

    private String deleteSql = "delete from idempotent_record where `expireTime` < ?";

    /**
     * 下面定时删除应该弄成分布式定时任务来处理好一点，这里为了方便就直接这样了
     */
    {
        Thread t = new Thread(()->{
            while (true){
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    int nums = jdbcTemplate.update(deleteSql,System.currentTimeMillis());
                    if (nums > 0){
                        log.info("now delete {} recode",nums);
                    }
                }catch (Exception e){
                    log.info("当前删除过期数据异常",e);
                }
            }
        });
        t.setName("idempotentMysqlSchedule-1");
        t.start();
    }
    @Override
    public IdempotentStorageTypeEnum type() {
        return IdempotentStorageTypeEnum.MYSQL;
    }

    /**
     * 这里可以使用请求合并的方式，批量获取数据
     * @param key
     * @return
     */
    @Override
    public String getValue(String key) {
        String sql = "select `value` from idempotent_record where `key` = ? and `expireTime` > ? limit 1";
        List<IdempotentRecord> records = jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(IdempotentRecord.class),key,System.currentTimeMillis());
        String value = null;
        if(!CollectionUtils.isEmpty(records)){
            value = records.get(0).getValue();
        }
        log.debug("Mysql Get key:{},value:{}",key,value);
        return value;
    }

    @Override
    public boolean setValue(String key, String value, int expireTime, TimeUnit timeUnit) {
        log.debug("Mysql Set key:{}, Value:{}, expireTime:{}, timeUnit:{}", key, value, expireTime, timeUnit);
        long date = System.currentTimeMillis();
        long millis = timeUnit.toMillis(expireTime);
        long expireDate = date + millis;
        String sql = "insert into idempotent_record(`key`,`value`,addTime,expireTime) values(?,?,?,?)";
        jdbcTemplate.update(sql, key, value, date, expireDate);
        return true;
    }
}
